/* 
泛型接口
*/

 /* 
  1. 声明泛型类型: 在接口名的右侧  <T>   // T K V
  2. 使用泛型: 接口体中
  3. 指定泛型的具体类型: 定义实现时, 接口名的右侧 <具体类型>
  */

  (() => {
    /* 
    泛型接口
    1. 定义泛型: 定义接口的接口名右侧: <T>
    2. 使用泛型: 接口体  T
    3. 指具体类型: 定义实现类时, 接口名的右侧: <具体类型名>
    */

    // 定义接口来约束所有管理类
    interface BaseCRUD<T> {
      data: T[];
      add (t: T): number;
      getById (id: number): T
    }

    class User {
      id?: number;
      name: string;
      age: number;
      constructor (name, age) {
        this.name = name
        this.age = age
      }
    }

   // 封装用户数据管理的类
    class UserCRUD implements BaseCRUD<User> {
      
      data: User[] = []; // 用来存储添加的user

      add (user: User): number { // 添加user, 返回新生成的id
        const id = this.data.length+1
        user.id = id
        this.data.push(user)
        return id
      }

      getById (id: number): User { // 根据id查找内部保存的user
        return this.data.find(user => user.id===id)
      }
    }

    const userCRUD = new UserCRUD()
    const id = userCRUD.add(new User('A', 18))
    userCRUD.add(new User('B', 19))
    console.log(userCRUD.data)
    console.log(userCRUD.getById(id))


    // 封装商品数据管理的类
    // class ProductCRUD {
    //   data: Product[] = [] // 内部存储的用户商品
    //   add (user: Product): number { // 添加一个商品, 返回其id
    //   }
    //   getById (id: number): Product { // 根据id获取一个商品
    //   }
    // }

  // 问题: 如何约束多个数据的管理类的API的一致性呢?
  // API: 语法 属性名都是data, 都是数组类型 / add() / getById()
  })()